/******************************************************************************\
 *                                                                            *
 *                          Craftmesh Model                                   *
 *                   Flavio Bertini fl.bertini@gmail.com                      *
 *                                                                            *
 *                                                                            *
\******************************************************************************/


#if !defined(__Craftmesh_model_h__)
#define __Craftmesh_model_h__


#include <limits>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <GL/freeglut.h>
#include "Const.h"
#include "Math.h"

#ifndef MAXVAL
#define MAXVAL 30
#endif

using namespace std;

typedef int indices[2];
typedef int indices_m[MAXVAL];

// MESH STUFF

// Vertex structure
struct Vertex
{
  float x, y, z;       		// coord. x, y, z
  int n_neigh;      		/* numero di vertici del primo ring */
  indices_m neigh,edge,face;
  int val;          		/* valenza del vertice */
  int bound;        		/* flag se e' di bordo */
  int tan;				/* indica se è un punto in tangenza*/
  int ins;				/* indica se è stato inserito in un edge */
};

// Edge structure
struct Edge
{
  indices neigh,vert;
  int val;             /* indica la valenza del lato; se di bordo o meno */
  int ic,ib,ie;        /* ic: indice all'array di curve; ib, ie: indici */
                         /*    al primo ed ultimo punto della curva */
  int tan;				/* flag di tangenza */
};

// Face structure
struct Face
{
  int          nVert;   		// num. of vertices
  vector<int> *vertId;  		// vertex index
  indices_m neigh,edge,vert;  	// vert; viene letto
  int val;                     	/* valenza della face; numero di facce del primo ring */
  int bound;                   	/* flag se e' di bordo */
  int pointInto;        		// numero di intersezioni interne
  int tan;						// flag di tangenza
  int bb;						// flag appartenenza bounding box di intersezione
};


// Class Mesh
class Mod_SubdivMesh
{
  public:
    string         filename,          // file name
                   filepath;          // file directory
    int            handId,            // capturing hand
                   nVert,             // num. of vertices
                   nEdge,		      // num. of edges
                   nFace;             // num. of faces
    Vertex         *vert,             // mesh vertices [1..nVert]
                   *fNorm;            // mesh normal   [1..nFace]
    Edge	  	   *edge;		      // mesh edges    [1..nEdge]
    Face           *face;             // mesh faces    [1..nFace]
    Mat_Vector     center,            // mesh center
                   transl;            // translation vector
    float          rCapture;          // sphere radius to capture the mesh
    float          scale[16],         // scale matrix and inverse
                   invsca[16],
                   rotat[16],         // rotation matrix and inverse
                   invrot[16];
    const GLfloat* color;             // mesh color
    bool           captured;          // the mesh is captured
    vector<int>    selectedVertices;  // list of selected vertices

    // constructors
    Mod_SubdivMesh();
    Mod_SubdivMesh(string fName, string fPath);
    ~Mod_SubdivMesh();

    // load file obj
    bool mod_load();
    bool mod_load(string fName, string fPath);
    /* prende in input la Mod_SubdivMesh "mesh" con vertici e facce
     e riempie tutti i campi previsti per la struttura Mod_SubdivMesh
     necessari per le operazioni booleane */
    void mod_LoadSubdivMesh();

    // save file obj
    bool mod_save();
    bool mod_save(string fName, string fPath);

    // copy source mesh in another mesh object
    void mod_copyMesh(Mod_SubdivMesh *Mdst);

    // set the mesh center coordinates
    void mod_setCenterAndRadius(void);

    // update the mesh center coordinates
    void mod_translateCenter(Mat_Vector trans);

    // draw the model
    void mod_drawMesh(void);

    // draw the model for anaglyph vision
    void mod_drawMeshSolid(void);

    // draw the catching sphere of the mesh
    void mod_drawCatchingSphere(void);

    // draw the reference cylinder of the mesh
    void mod_drawRefCylinder(int visionMode);

    // apply the transformations
    void mod_applyTransformations(void);

    // draw the selected vertices
    void mod_drawSelectedVertices(int);

    //// search in a face for a given vertex index
    int mod_find_in_face(Face *face,int ind_face, int ind_vert);

    // search a vertex with a given face index
    int mod_find_in_vert_face(Vertex *vert,int ind_vert, int ind_face);

    // search a vertex index with a given vertex
    int mod_find_in_vert(Vertex v);

    // Funzioni per l'interrogazione degli elementi costitutivi di una mesh
    void mod_inquiryV(int index);
    void mod_inquiryE(int index);
    void mod_inquiryF(int index);

  private:

    // Print an error message
    void ErrorMessage();
    // swap two int
    void swap_int(int *a, int *b);


}; // Class Subdivision Mesh

#endif // __Craftmesh_model_h__
